const fs = require('fs');
const path = require('path');
const https = require('https');




/** 文件操作 */
class Myfs {
    /**
    * @description 删除单个文件
    * @param {string} filePath 
    * @returns {boolean} 是否删除成功
    */
    static delFile = (filePath) => {
        if (fs.existsSync(filePath)) {
            fs.unlinkSync(filePath);
            return true;
        } else {
            return false;
        }
    }


    /**
     * @description 删除空文件夹
     * @param {string} dirPath 
     * @returns {boolean} 是否删除成功
     */
    static delEmptyDir = (dirPath) => {
        const files = fs.readdirSync(dirPath);
        if (fs.existsSync(dirPath) && files.length === 0) {
            fs.rmdirSync(dirPath);
            return true;
        } else {
            return false;
        }
    }

    /**
     * @description 删除文件夹
     * @param {string} dirPath 
     * @returns {boolean} 是否删除成功
     */
    static delDir = (dirPath) => {
        if (fs.existsSync(dirPath)) {
            var files = fs.readdirSync(dirPath);
            files.forEach(function (item) {
                var item_path = `${dirPath}/${item}`;
                if (fs.statSync(item_path).isDirectory()) {
                    Myfs.delDir(item_path);
                } else {
                    Myfs.delFile(item_path);
                }
            });
            Myfs.delEmptyDir(dirPath);
            return true;
        } else {
            return false;
        }
    }


    /**
     * @description 清空文件夹
     * @param {string} dirPath 
     * @returns {boolean} 是否清空成功
     */
    static clearDir = (dirPath) => {
        if (fs.existsSync(dirPath) === false) {
            return false;
        }
        const files = fs.readdirSync(dirPath);
        files.forEach(function (item) {
            const item_path = `${dirPath}/${item}`;
            if (fs.statSync(item_path).isDirectory()) {
                Myfs.delDir(item_path);
            } else {
                Myfs.delFile(item_path);
            }
        });
        return true;
    }


    /**
     * @description 复制单个文件
     * @param {string} from 
     * @param {string} to 
     * @returns {boolean} 是否复制成功
     */
    static copyFile = (from, to) => {
        if (!fs.existsSync(from)) {
            return false;
        } else {
            fs.copyFileSync(from, to);
            return true;
        }
    }



    /**
     * @description 拷贝文件夹
     * @param {string} from 
     * @param {string} to 
     */
    static copyDir = (from, to) => {
        const fromPath = path.resolve(from);
        const toPath = path.resolve(to);
        fs.access(toPath, function (err) {
            if (err) {
                fs.mkdirSync(toPath);
            }
        })
        fs.readdir(fromPath, function (err, paths) {
            if (err) {
                console.log(err);
                return false;
            }
            paths.forEach(function (item) {
                const newFromPath = fromPath + '/' + item;
                const newToPath = path.resolve(toPath + '/' + item);
                fs.stat(newFromPath, function (err, stat) {
                    if (err) {
                        console.log(err);
                        return false;
                    };
                    if (stat.isFile()) {
                        Myfs.copyFile(newFromPath, newToPath);
                    }
                    if (stat.isDirectory()) {
                        Myfs.copyDir(newFromPath, newToPath);
                    }
                })
            });
        });
        return true;
    }


    /**
     * 不存在文件夹，直接创建
     * @param realPath 
     * @returns Promise<void>
     */
    static autoCreatDir = async (realPath) => {
        const dirpath = path.resolve(realPath)
        try {
            await fs.promises.stat(dirpath);
        } catch (e) {
            // {recursive: true} 这个配置项是配置自动创建多层文件夹
            await fs.promises.mkdir(dirpath, {
                recursive: true
            });
        }
        return Promise.resolve(undefined);
    };


    /**
     * 不存在文件夹，直接创建
     * @param dirs 文件夹目录数组 [`./dist/assets`, `./dist/browser`] 
     * @returns Promise<void>
     */
    static autoCreatDirs = async (dirs) => {
        for (let i = 0; i < dirs.length; i++) {
            await Myfs.autoCreatDir(dirs[i]);
        }
        return Promise.resolve(undefined);
    };


    /**
     * @description 读取文件夹内文件
     * @param {string} dirPath 文件夹路径
     * @returns {Promise<Array<string>>} 文件内容
     */
    static dirFiles = async (dirPath) => {
        const result = [];
        try {
            const files = fs.readdirSync(dirPath);
            files.forEach(file => {
                result.push(file);
            });
            return Promise.resolve(result);
        } catch {
            return Promise.resolve(result);
        }
    };

    /**
     * 网络下载文件
     * @param url 文件地址
     * @param filePath 下载到路径
     * @returns 是否成功
     */
    static download = async (url, filePath) => {
        return new Promise((resolve) => {
            https.get(url, (res) => {
                // Open file in local filesystem
                const file = fs.createWriteStream(`${filePath}`);
                // Write data into local file
                res.pipe(file);
                // Close the file
                file.on('finish', () => {
                    file.close();
                    resolve(true);
                });
            }).on("error", (err) => {
                resolve(false);
            });
        });
    };


    /**
     * 获取本地目录的文件根文件夹
     * @param {string} localDir 
     * @returns { dirs: string[], files: string[] } 
     */
    static getFileAndDirList = (localDir) => {
        let dirs = [];
        let files = [];
        const dir = fs.readdirSync(localDir);

        for (var i = 0; i < dir.length; i++) {
            var p = path.join(localDir, dir[i]);
            var stat = fs.statSync(p);
            if (stat.isDirectory()) {
                dirs.push(p.replace(/[\\]/g, '/'));
                const res = Myfs.getFileAndDirList(p);
                dirs = dirs.concat(res.dirs);
                files = files.concat(res.files);
            }
            else {
                files.push(p.replace(/[\\]/g, '/'));
            }
        }

        return { dirs, files };
        // console.log({dirs, files});
    }
    /** 读取文件 */
    static readFile = (filePath) => {
        filePath = path.resolve(filePath);
        const data = fs.readFileSync(filePath, 'utf8');
        return data;
    }
    /** 读取文件 */
    static readFiles = (filePaths) => {
        let str = '';
        for (let i = 0; i < filePaths.length; i++) {
            const filePath = filePaths[i];
            str += Myfs.readFile(filePath);
        }
        return str;
    }
    /** 读取文件夹内文件 */
    static readDirFiles = async (dirPath) => {
        const fs = require('fs').promises;
        const path = require('path');
        let result = '';
        try {
            // 获取目录中的文件和文件夹列表
            const entries = await fs.readdir(dirPath, { withFileTypes: true });

            // 遍历目录中的每个条目
            for (let entry of entries) {
                const entryPath = path.join(dirPath, entry.name);

                // 如果是文件夹，则递归调用
                if (entry.isDirectory()) {
                    result += await Myfs.readDirFiles(entryPath);
                } else if (entry.isFile()) {
                    // 如果是文件，则读取文件内容（如果需要）
                    const content = await fs.readFile(entryPath, 'utf8');;
                    result += `\nFile: ${entryPath}\n${content}`
                }
            }

            return Promise.resolve(result);
        } catch (error) {
            console.error('Error reading directory:', error);
            return Promise.resolve('');
        }
    }
    /** 写入字符串 */
    static writeFile = async (filePath, str) => {
        const regex = /^(.*\/)?(.+)$/;
        const match = filePath.match(regex);
        const folderPath = match[1] ? match[1] : '';
        const fileName = match[2]; 
        if(folderPath){
            await Myfs.autoCreatDir(folderPath);
        }
        filePath = path.resolve(filePath);
        fs.writeFileSync(filePath, str, 'utf8');
    }
    /** 检查文件是否存在 */
    static isFileExist = (filePath) => {
        try{
            fs.accessSync(filePath, fs.constants.F_OK);
            return true;
        } catch (_) {
            return false;
        } 
    }
}




module.exports = {
    Myfs,
};